package com.kuaishou.locallife.open.api.common.utils.adapter;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;

/**
 * TypeAdapter适配器
 *
 * @author shuxiaohui <shuxiaohui@kuaishou.com>
 * Created on 2020-03-31
 */
public class CustomizedTypeAdapter extends TypeAdapter<Object> {

    @Override
    public void write(JsonWriter out, Object value) throws IOException {
        LazyHolder.LAZY.write(out, value);
    }

    @Override
    public Object read(JsonReader in) throws IOException {
        JsonToken token = in.peek();
        switch (token) {
            case BEGIN_ARRAY:
                List<Object> list = new ArrayList<Object>();
                in.beginArray();
                while (in.hasNext()) {
                    list.add(read(in));
                }
                in.endArray();
                return list;

            case BEGIN_OBJECT:
                Map<String, Object> map = new HashMap<String, Object>();
                in.beginObject();
                while (in.hasNext()) {
                    map.put(in.nextName(), read(in));
                }
                in.endObject();
                return map;

            case STRING:
                return in.nextString();

            case NUMBER: // override
                double raw = in.nextDouble();
                BigDecimal bigDecimal = new BigDecimal(Math.abs(raw)); // always compare positive
                if (bigDecimal.compareTo(new BigDecimal(Long.MAX_VALUE)) > 0) {
                    return raw;
                }
                if (bigDecimal.compareTo(new BigDecimal(Integer.MAX_VALUE)) > 0) {
                    return (long) raw;
                }
                return (int) raw;

            case BOOLEAN:
                return in.nextBoolean();

            case NULL:
                in.nextNull();
                return null;

            default:
                throw new IllegalStateException();
        }
    }

    private static final class LazyHolder {
        static final TypeAdapter<Object> LAZY = new Gson().getAdapter(Object.class);
    }
}
